<?php

namespace app\model\oa;

use app\model\BaseModel;

/**
 * 工作排班模型
 * 对应数据表：oa_work_schedule
 */
class WorkSchedule extends BaseModel
{
    /**
     * 数据表名
     * @var string
     */
    protected $name = 'work_schedule';

    /**
     * 主键名
     * @var string
     */
    protected $pk = 'id';

    /**
     * 字段类型转换
     * @var array
     */
    protected $type = [
        'id' => 'integer',
        'admin_id' => 'integer',
        'schedule_date' => 'integer',
        'start_time' => 'integer',
        'end_time' => 'integer',
        'work_type' => 'integer',
        'status' => 'integer',
        'remark' => 'string',
        'create_time' => 'integer',
        'update_time' => 'integer',
    ];

    /**
     * 可搜索字段
     * @var array
     */
    protected $searchField = ['remark'];

    /**
     * 工作类型
     * @var array
     */
    public const WORK_TYPE = [
        1 => '正常上班',
        2 => '加班',
        3 => '调休',
        4 => '请假',
        5 => '出差',
    ];

    /**
     * 排班状态
     * @var array
     */
    public const STATUS = [
        1 => '已排班',
        2 => '进行中',
        3 => '已完成',
        4 => '已取消',
    ];

    /**
     * 关联管理员
     * @return \think\model\relation\BelongsTo
     */
    public function admin()
    {
        return $this->belongsTo('app\model\admin\User', 'admin_id', 'id');
    }

    /**
     * 获取排班列表
     * @param array $params 查询参数
     * @return \think\Paginator
     */
    public function getScheduleList($params = [])
    {
        $where = [];
        
        if (!empty($params['admin_id'])) {
            $where[] = ['admin_id', '=', $params['admin_id']];
        }
        
        if (!empty($params['work_type'])) {
            $where[] = ['work_type', '=', $params['work_type']];
        }
        
        if (isset($params['status']) && $params['status'] !== '') {
            $where[] = ['status', '=', $params['status']];
        }
        
        if (!empty($params['start_date'])) {
            $where[] = ['schedule_date', '>=', strtotime($params['start_date'])];
        }
        
        if (!empty($params['end_date'])) {
            $where[] = ['schedule_date', '<=', strtotime($params['end_date'] . ' 23:59:59')];
        }

        return $this->where($where)
            ->with(['admin'])
            ->order('schedule_date', 'desc')
            ->order('start_time', 'asc')
            ->paginate([
                'list_rows' => $params['limit'] ?? 15,
                'page' => $params['page'] ?? 1,
            ]);
    }

    /**
     * 获取员工排班
     * @param int $adminId 管理员ID
     * @param string $startDate 开始日期
     * @param string $endDate 结束日期
     * @return array
     */
    public function getAdminSchedule($adminId, $startDate, $endDate)
    {
        $startTime = strtotime($startDate);
        $endTime = strtotime($endDate . ' 23:59:59');

        return $this->where('admin_id', $adminId)
            ->where('schedule_date', '>=', $startTime)
            ->where('schedule_date', '<=', $endTime)
            ->order('schedule_date', 'asc')
            ->order('start_time', 'asc')
            ->select()
            ->toArray();
    }

    /**
     * 获取某天排班
     * @param string $date 日期
     * @param int $adminId 管理员ID
     * @return array
     */
    public function getDailySchedule($date, $adminId = null)
    {
        $startTime = strtotime($date);
        $endTime = strtotime($date . ' 23:59:59');

        $where = [
            ['schedule_date', '>=', $startTime],
            ['schedule_date', '<=', $endTime]
        ];

        if ($adminId) {
            $where[] = ['admin_id', '=', $adminId];
        }

        return $this->where($where)
            ->with(['admin'])
            ->order('start_time', 'asc')
            ->select()
            ->toArray();
    }

    /**
     * 检查排班冲突
     * @param int $adminId 管理员ID
     * @param int $scheduleDate 排班日期
     * @param int $startTime 开始时间
     * @param int $endTime 结束时间
     * @param int $excludeId 排除的排班ID
     * @return bool
     */
    public function checkScheduleConflict($adminId, $scheduleDate, $startTime, $endTime, $excludeId = 0)
    {
        $where = [
            ['admin_id', '=', $adminId],
            ['schedule_date', '=', $scheduleDate],
            ['status', '<>', 4], // 排除已取消的
            ['id', '<>', $excludeId]
        ];

        // 检查时间冲突
        $conflict = $this->where($where)
            ->where(function ($query) use ($startTime, $endTime) {
                $query->where(function ($query) use ($startTime, $endTime) {
                    $query->where('start_time', '<=', $startTime)
                        ->where('end_time', '>', $startTime);
                })->whereOr(function ($query) use ($startTime, $endTime) {
                    $query->where('start_time', '<', $endTime)
                        ->where('end_time', '>=', $endTime);
                })->whereOr(function ($query) use ($startTime, $endTime) {
                    $query->where('start_time', '>=', $startTime)
                        ->where('end_time', '<=', $endTime);
                });
            })
            ->find();

        return !empty($conflict);
    }

    /**
     * 添加排班
     * @param array $data 排班数据
     * @return bool|int
     */
    public function addSchedule($data)
    {
        // 转换时间格式
        $data['schedule_date'] = strtotime($data['schedule_date']);
        $data['start_time'] = strtotime($data['start_time']);
        $data['end_time'] = strtotime($data['end_time']);

        // 检查冲突
        if ($this->checkScheduleConflict(
            $data['admin_id'],
            $data['schedule_date'],
            $data['start_time'],
            $data['end_time']
        )) {
            return false;
        }

        $data['status'] = 1; // 已排班
        $data['create_time'] = time();
        $data['update_time'] = time();
        
        return $this->insertGetId($data);
    }

    /**
     * 更新排班
     * @param int $id 排班ID
     * @param array $data 更新数据
     * @return bool
     */
    public function updateSchedule($id, $data): bool
    {
        // 转换时间格式
        if (isset($data['schedule_date'])) {
            $data['schedule_date'] = strtotime($data['schedule_date']);
        }
        if (isset($data['start_time'])) {
            $data['start_time'] = strtotime($data['start_time']);
        }
        if (isset($data['end_time'])) {
            $data['end_time'] = strtotime($data['end_time']);
        }

        // 获取原记录
        $schedule = $this->find($id);
        if (!$schedule) {
            return false;
        }

        // 检查冲突
        $adminId = $data['admin_id'] ?? $schedule['admin_id'];
        $scheduleDate = $data['schedule_date'] ?? $schedule['schedule_date'];
        $startTime = $data['start_time'] ?? $schedule['start_time'];
        $endTime = $data['end_time'] ?? $schedule['end_time'];

        if ($this->checkScheduleConflict($adminId, $scheduleDate, $startTime, $endTime, $id)) {
            return false;
        }

        $data['update_time'] = time();
        
        // 确保返回布尔值
        $result = $this->where('id', $id)->update($data);
        return $result !== false;
    }

    /**
     * 取消排班
     * @param int|array $ids 排班ID
     * @return bool
     */
    public function cancelSchedule($ids): bool
    {
        $updateData = [
            'status' => 4,
            'update_time' => time()
        ];
        
        if (is_array($ids)) {
            $result = $this->where('id', 'in', $ids)->update($updateData);
        } else {
            $result = $this->where('id', $ids)->update($updateData);
        }
        
        return $result !== false;
    }

    /**
     * 完成排班
     * @param int|array $ids 排班ID
     * @return bool
     */
    public function completeSchedule($ids): bool
    {
        $updateData = [
            'status' => 3,
            'update_time' => time()
        ];
        
        if (is_array($ids)) {
            $result = $this->where('id', 'in', $ids)->update($updateData);
        } else {
            $result = $this->where('id', $ids)->update($updateData);
        }
        
        return $result !== false;
    }

    /**
     * 获取排班统计
     * @param string $startDate 开始日期
     * @param string $endDate 结束日期
     * @param int $adminId 管理员ID
     * @return array
     */
    public function getScheduleStats($startDate, $endDate, $adminId = null)
    {
        $startTime = strtotime($startDate);
        $endTime = strtotime($endDate . ' 23:59:59');

        $where = [
            ['schedule_date', '>=', $startTime],
            ['schedule_date', '<=', $endTime]
        ];

        if ($adminId) {
            $where[] = ['admin_id', '=', $adminId];
        }

        $stats = $this->where($where)
            ->field('work_type, status, COUNT(*) as count')
            ->group('work_type, status')
            ->select()
            ->toArray();

        $result = [
            'total' => 0,
            'type_stats' => [],
            'status_stats' => []
        ];

        foreach ($stats as $stat) {
            $result['total'] += $stat['count'];
            
            if (!isset($result['type_stats'][$stat['work_type']])) {
                $result['type_stats'][$stat['work_type']] = 0;
            }
            $result['type_stats'][$stat['work_type']] += $stat['count'];
            
            if (!isset($result['status_stats'][$stat['status']])) {
                $result['status_stats'][$stat['status']] = 0;
            }
            $result['status_stats'][$stat['status']] += $stat['count'];
        }

        return $result;
    }

    /**
     * 删除排班
     * @param int|array $ids 排班ID
     * @return bool
     */
    public function deleteSchedule($ids): bool
    {
        if (is_array($ids)) {
            $result = $this->where('id', 'in', $ids)->delete();
        } else {
            $result = $this->where('id', $ids)->delete();
        }
        
        return $result !== false;
    }

    /**
     * 搜索器：按管理员ID搜索
     * @param \think\db\Query $query
     * @param int $value
     */
    public function searchAdminIdAttr($query, $value)
    {
        $query->where('admin_id', $value);
    }

    /**
     * 搜索器：按工作类型搜索
     * @param \think\db\Query $query
     * @param int $value
     */
    public function searchWorkTypeAttr($query, $value)
    {
        $query->where('work_type', $value);
    }

    /**
     * 搜索器：按状态搜索
     * @param \think\db\Query $query
     * @param int $value
     */
    public function searchStatusAttr($query, $value)
    {
        $query->where('status', $value);
    }

    /**
     * 搜索器：按排班日期搜索
     * @param \think\db\Query $query
     * @param string $value
     */
    public function searchScheduleDateAttr($query, $value)
    {
        if (is_string($value)) {
            $startTime = strtotime($value);
            $endTime = strtotime($value . ' 23:59:59');
            $query->whereBetween('schedule_date', [$startTime, $endTime]);
        }
    }

    /**
     * 搜索器：按日期范围搜索
     * @param \think\db\Query $query
     * @param array $value
     */
    public function searchDateRangeAttr($query, $value)
    {
        if (is_array($value) && count($value) === 2) {
            $startTime = strtotime($value[0]);
            $endTime = strtotime($value[1] . ' 23:59:59');
            $query->whereBetween('schedule_date', [$startTime, $endTime]);
        }
    }
}